#include "util.h"
#include <QStack>

util::util()
{

}


static double opTwoOprand(QChar op,double s2,double s1){
    switch (op.toLatin1()) {
    case '+':

        return s1 + s2;
    case '-':

        return s2 - s1;
    case '*':

        return  s2 * s1;
    case '/':

        return  s2 / s1;
    default:
        return 0;
    }
}

double evalExpresion(QString expr){

    QStack<QChar> opcode;
    QStack<double> oprand;

    for(int i=0;i<expr.length();){

        if(QChar::isDigit(expr[i].toLatin1())){
            QString oprandStr;
            oprandStr.append(expr[i]);
            while(++i<expr.length()&&(QChar::isDigit(expr[i].toLatin1())||QChar::fromLatin1('.')==expr[i])){
                 oprandStr.append(expr[i]);
            }
            oprand.push(oprandStr.toDouble());

        }else{


            QChar op;
            if(!opcode.isEmpty()){
                  op= opcode.top();
            }

            QChar iop = expr[i];
            switch (iop.toLatin1()){

                case '+':
                case '-':
                    if(!op.isNull()&&(
                                op == QChar::fromLatin1('*') || op == QChar::fromLatin1('/')||
                                op == QChar::fromLatin1('+') || op == QChar::fromLatin1('-')
                                )){

                        double s1 = oprand.pop();
                        double s2 = oprand.pop();
                        oprand.push(opTwoOprand(op,s2,s1));
                        opcode.pop();
                    }
                    opcode.push(iop);
                    break;
                case '*':
                case '/':

                    if(!op.isNull()&&(op == QChar::fromLatin1('*') || op == QChar::fromLatin1('/'))){

                            double s1 = oprand.pop();
                            double s2 = oprand.pop();
                            oprand.push(opTwoOprand(op,s2,s1));
                            opcode.pop();

                    }

                    opcode.push(iop);
                    break;
                case '(':
                    opcode.push(iop);
                    break;
                case ')':
                    if(!op.isNull()){
                        op = opcode.pop();
                        if(op == QChar::fromLatin1('*') || op == QChar::fromLatin1('/')){
                            double s1 = oprand.pop();
                            double s2 = oprand.pop();
                            oprand.push(opTwoOprand(op,s2,s1));
                            op = opcode.pop();
                        }
                        QStack<QChar> opcodeReverse;
                        QStack<double> oprandReverse;
                        while(op != QChar::fromLatin1('(')){

                            opcodeReverse.push(op);
                            oprandReverse.push(oprand.pop());

                            op = opcode.pop();
                        }
                        if(!opcodeReverse.isEmpty()){
                            oprandReverse.push(oprand.pop());

                            do{
                                op = opcodeReverse.pop();
                                double s1 = oprandReverse.pop();
                                double s2 = oprandReverse.pop();
                                oprandReverse.push(opTwoOprand(op,s1,s2));
                            }while(!opcodeReverse.isEmpty());

                            oprand.push(oprandReverse.pop());
                        }




                    }

                    break;

            }


            i++;
        }

    }


    QStack<QChar> opcodeReverse;
    QStack<double> oprandReverse;
    while(!oprand.isEmpty()){
        oprandReverse.push(oprand.pop());
    }
    while(!opcode.isEmpty()){
        opcodeReverse.push(opcode.pop());
    }


    do{
        QChar op = opcodeReverse.pop();
        double s1 = oprandReverse.pop();
        double s2 = oprandReverse.pop();
        oprandReverse.push(opTwoOprand(op,s1,s2));
    }while(!opcodeReverse.isEmpty());



    return oprandReverse.top();

}
